package util

import (
	"errors"
	"fmt"
	"github.com/bwmarrin/snowflake"
	jsoniter "github.com/json-iterator/go"
	"math/rand"
	"reflect"
	"regexp"
	"strings"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

const (
	Num    = "123456789"
	UppStr = "ABCDEFGHIJKLMNPQRSTUVWXYZ"
	LowStr = "abcdefghijklmnpqrstuvwxyz"
)

// 随机生成指定位数的大写字母和数字的组合
func GetStrongPasswordString(l int) string {
	//~!@#$%^&*()_+{}":?><;.,
	//str := "123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz!@#$%&*"
	str := "123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz"
	bytes := []byte(str)
	result := []byte{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < l; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}

	ok1, _ := regexp.MatchString(".[1|2|3|4|5|6|7|8|9]", string(result))
	ok2, _ := regexp.MatchString(".[Z|X|C|V|B|N|M|A|S|D|F|G|H|J|K|L|Q|W|E|R|T|Y|U|I|P]", string(result))
	ok3, _ := regexp.MatchString(".[z|x|c|v|b|n|m|a|s|d|f|g|h|j|k|l|q|w|e|r|t|y|u|i|p]", string(result))
	//ok4, _ := regexp.MatchString(".[!|@|#|$|%|&|*]", string(result))
	if ok1 && ok2 && ok3 {
		return string(result)
	} else {
		return GetStrongPasswordString(l)
	}

}

// RandStringRunes 返回随机字符串
func RandStringRunes(n int) string {
	var letterRunes = []rune("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

// RandStringRunesV1 返回随机字符串
func RandStringRunesV1(letterRunes []rune, n int) string {
	if len(letterRunes) == 0 {
		letterRunes = []rune(Num + UppStr + LowStr)
	}

	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

// ContainsUint 返回list中是否包含
func ContainsUint(s []uint, e uint) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

// GetMonthDays 获取某月有多少天
func GetMonthDays(year int, month int) int {
	days := 0
	if month != 2 {
		if month == 4 || month == 6 || month == 9 || month == 11 {
			days = 30
		} else {
			days = 31
		}
	} else {
		if IsLeapYear(year) {
			days = 29
		} else {
			days = 28
		}
	}
	return days
}

// IsLeapYear 判断是否为闰年
func IsLeapYear(year int) bool { // y == 2000, 2004
	// 判断是否为闰年
	if year%4 == 0 && year%100 != 0 || year%400 == 0 {
		return true
	}

	return false
}

// ContainsString 返回list中是否包含
func ContainsString(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

// Replace 根据替换表执行批量替换
func Replace(table map[string]string, s string) string {
	for key, value := range table {
		s = strings.Replace(s, key, value, -1)
	}
	return s
}

// BuildRegexp 构建用于SQL查询用的多条件正则
func BuildRegexp(search []string, prefix, suffix, condition string) string {
	var res string
	for key, value := range search {
		res += prefix + regexp.QuoteMeta(value) + suffix
		if key < len(search)-1 {
			res += condition
		}
	}
	return res
}

// BuildConcat 根据数据库类型构建字符串连接表达式
func BuildConcat(str1, str2 string, DBType string) string {
	switch DBType {
	case "mysql":
		return "CONCAT(" + str1 + "," + str2 + ")"
	default:
		return str1 + "||" + str2
	}
}

// SliceIntersect 求两个切片交集
func SliceIntersect(slice1, slice2 []string) []string {
	m := make(map[string]int)
	nn := make([]string, 0)
	for _, v := range slice1 {
		m[v]++
	}

	for _, v := range slice2 {
		times, _ := m[v]
		if times == 1 {
			nn = append(nn, v)
		}
	}
	return nn
}

// SliceDifference 求两个切片差集
func SliceDifference(slice1, slice2 []string) []string {
	m := make(map[string]int)
	nn := make([]string, 0)
	inter := SliceIntersect(slice1, slice2)
	for _, v := range inter {
		m[v]++
	}

	for _, value := range slice1 {
		times, _ := m[value]
		if times == 0 {
			nn = append(nn, value)
		}
	}
	return nn
}

// 对字符串使用任意字符分隔
func StrSplitAny(s string, seps string) []string {
	splitter := func(r rune) bool {
		return strings.ContainsRune(seps, r)
	}
	return strings.FieldsFunc(s, splitter)
}

// sql like 验证
func SqlLikePaste(keyStr string) string {
	//keyStr = strings.Replace(keyStr, "\\", "\\\\", -1)
	keyStr = strings.Replace(keyStr, "%", "\\%", -1)
	return keyStr
}

// 雪花算法
var node *snowflake.Node

func Init(startTime string, machineID int64) (err error) {
	var st time.Time
	// 格式化 1月2号下午3时4分5秒  2006年
	st, err = time.Parse(time.DateOnly, startTime)
	if err != nil {
		fmt.Println(err)
		return
	}

	snowflake.Epoch = st.UnixNano() / 1e6
	node, err = snowflake.NewNode(machineID)
	if err != nil {
		fmt.Println(err)
		return
	}

	return
}

// 生成 64 位的 雪花 ID
func GenSnowflakeID(startTime string, machineID int64) (int64, error) {
	if err := Init(startTime, machineID); err != nil {
		fmt.Println("Init() failed, err = ", err)
		return 0, err
	}
	return node.Generate().Int64(), nil
}

// 根据struct获取 tag 名称
func GetStructTagValue(MyStruct interface{}, tagName, fieldName string) (string, error) {
	// 获取字段的JSON标签值
	jsonTag, ok := reflect.TypeOf(MyStruct).FieldByName(fieldName)
	if !ok {
		return "", fmt.Errorf("field %s not found in struct", fieldName)
	}
	return jsonTag.Tag.Get(tagName), nil
}

// 请求参数不能为空
func ParamIsNull(param string) error {
	return errors.New(param + " 参数不能为空")
}

func NewJsonTag(tagName string) jsoniter.API {
	return jsoniter.Config{
		EscapeHTML:             true,
		SortMapKeys:            true,
		ValidateJsonRawMessage: true,
		TagKey:                 tagName,
	}.Froze()
}
